<template>
  <div ref="chartRef" class="chart-container" :style="{
    width: responsive ? '100%' : width,
    height: responsive ? '100%' : height,
  }"></div>
</template>

<script setup>
import * as echarts from "echarts/core";
import {
  TitleComponent,
  TooltipComponent,
  LegendComponent,
  GridComponent,
  DataZoomComponent,
  MarkLineComponent,
  ToolboxComponent,
} from "echarts/components";
import { LineChart, BarChart } from "echarts/charts";
import { UniversalTransition } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";
import { onMounted, onUnmounted, ref, watch, onActivated } from "vue";

// 注册必要的组件
echarts.use([
  TitleComponent,
  TooltipComponent,
  LegendComponent,
  GridComponent,
  DataZoomComponent,
  MarkLineComponent,
  ToolboxComponent,
  LineChart,
  BarChart,
  CanvasRenderer,
  UniversalTransition,
]);

// Props 定义
const props = defineProps({
  options: {
    type: Object,
    required: true,
    default: () => ({}),
  },
  width: {
    type: String,
    default: "100%",
  },
  height: {
    type: String,
    default: "400px",
  },
  theme: {
    type: String,
    default: "default",
  },
  responsive: {
    type: Boolean,
    default: true,
  },
});

// 图表相关变量
const chartRef = ref(null);
let chartInstance = null;
let resizeObserver = null;
let isResizing = false;

// 防抖函数
const debounce = (fn, delay) => {
  let timer = null;
  return (...args) => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
};

// 颜色配置
const colorPalette = [
  "#409EFF",
  "#7dafff",
  "#ee7a18",
  "#67C23A",
  "#E6A23C",
  "#F56C6C",
  "#909399",
];

// 基础配置生成函数
const createBaseOption = () => ({
  backgroundColor: "#ffffff",
  animation: true,
  color: colorPalette,
  toolbox: {
    show: true,
    feature: {
      saveAsImage: {
        type: 'png',
        title: '保存为图片',
        pixelRatio: 2,
        backgroundColor: '#fff'
      }
    },
    right: '20px',
  },
  animationDuration: 300,
  animationEasing: "cubicInOut",
  animationThreshold: 1500,
  progressiveThreshold: 2000,
  progressive: 150,
  hoverLayerThreshold: 2000,
  tooltip: {
    trigger: "axis",
    axisPointer: {
      type: "cross",
      crossStyle: {
        width: 1,
        type: "dashed",
        color: "#aaa",
      },
    },
    formatter: function (params) {
      const yAxisUnit = props.options.yAxisUnit || '';
      const secondYAxisUnit = props.options.secondYAxisUnit || '';

      let result = params[0].axisValueLabel + '<br/>';
      params.forEach(param => {
        const unit = param.componentIndex === 1 || param.data?.yAxisIndex === 1
          ? secondYAxisUnit
          : yAxisUnit;

        result += param.marker + param.seriesName.split('(')[0].trim() + ': ' +
          param.value + (unit ? ' ' + unit : '') + '<br/>';
      });
      return result;
    },
    textStyle: { fontSize: 12 },
    padding: [8, 12],
    borderRadius: 4,
    borderWidth: 0,
    backgroundColor: "rgba(255, 255, 255, 0.9)",
    shadowColor: "rgba(0, 0, 0, 0.1)",
    shadowBlur: 3,
    shadowOffsetX: 0,
    shadowOffsetY: 0,
    transitionDuration: 0.4,
    position: function (point, params, dom, rect, size) {
      const [x, y] = point;
      const { contentSize, viewSize } = size;
      const { width: tooltipWidth, height: tooltipHeight } = contentSize;
      const gap = 20;

      let posX = x + gap;
      let posY = y + gap;

      if (posX + tooltipWidth > viewSize.width) {
        posX = Math.max(x - tooltipWidth - gap, 0);
      }

      if (posY + tooltipHeight > viewSize.height) {
        posY = Math.max(y - tooltipHeight - gap, 0);
      }

      if (tooltipWidth > viewSize.width) {
        posX = 0;
      }

      return [posX, posY];
    },
    confine: true,
  },
});
// 修改 createSeriesConfig 函数来处理 extra 属性
const createSeriesConfig = (series, customColors, isStacked, showMarkLine) => {
  const { hideXAxis, hideYAxis } = props.options;
  return series.map((s, index) => {
    // 提取 extra 属性（如果存在）
    const { extra = {}, ...seriesWithoutExtra } = s;

    // 创建基础配置，并合并 extra 属性
    const baseConfig = {
      ...seriesWithoutExtra,
      ...extra, // 直接合并 extra 中的所有属性
      itemStyle: {
        color: customColors[index % customColors.length],
        borderRadius: s.type === "bar" ? [4, 4, 0, 0] : 0,
      },
    };

    if (s.type === "line") {
      const lineColor = customColors[index % customColors.length];
      const rgbColor = lineColor.replace(/^#/, '').match(/.{2}/g).map(v => parseInt(v, 16));
      const transparentShadowColor = `rgba(${rgbColor[0]}, ${rgbColor[1]}, ${rgbColor[2]}, 0.2)`;

      Object.assign(baseConfig, {
        smooth: 0.2,
        showSymbol: !(hideXAxis || hideYAxis),
        symbol: "circle",
        symbolSize: 6,
        lineStyle: {
          width: 2,
          cap: "round",
        },
        emphasis: {
          focus: "series",
          scale: false,
          itemStyle: {
            borderWidth: 2,
          },
          lineStyle: {
            color: lineColor,
            shadowColor: transparentShadowColor,
            shadowBlur: 3,
            shadowOffsetX: 0,
            shadowOffsetY: 0,
          }
        },
      });
    }

    if (s.type === "bar") {
      Object.assign(baseConfig, {
        barMaxWidth: 80,
        stack: isStacked ? "total" : undefined,
        emphasis: {
          focus: "series",
          itemStyle: {
            shadowColor: "rgba(0,0,0,0.3)",
            shadowBlur: 3,
            shadowOffsetX: 0,
            shadowOffsetY: 5,
          },
        },
      });
    }

    if (showMarkLine && s.showExtremum) {
      baseConfig.markLine = {
        silent: true,
        animation: true,
        symbol: ["none", "none"],
        precision: 2,
        label: {
          formatter: ({ data }) => {
            if (!data) return "";
            const value = typeof data.value === "number"
              ? data.value.toFixed(2)
              : data.value;
            const unit = s.yAxisIndex === 1
              ? props.options.secondYAxisUnit
              : props.options.yAxisUnit || '';
            return `${data.name}: ${value}${unit}`;
          },
          position: "insideEndTop",
          fontSize: 11,
          color: "#666",
          padding: [2, 4],
          backgroundColor: "rgba(255, 255, 255, 0.8)",
          borderRadius: 2,
        },
        lineStyle: {
          type: "dashed",
          width: 1,
          opacity: 0.8,
        },
        data: [
          {
            type: "average",
            name: "平均值",
            lineStyle: { color: "#FFB100" },
          },
          {
            type: "max",
            name: "最大值",
            lineStyle: { color: "#FF6B6B" },
          },
          {
            type: "min",
            name: "最小值",
            lineStyle: { color: "#4ECDC4" },
          },
        ],
        animationDuration: 300,
        animationEasing: "cubicInOut",
      };
    }

    return baseConfig;
  });
};

// 强制重绘函数
const forceResize = () => {
  if (chartInstance) {
    setTimeout(() => {
      const currentAnimation = chartInstance.getOption().animation;
      chartInstance.setOption({
        animation: false
      });
      chartInstance.resize();
      chartInstance.setOption({
        animation: currentAnimation
      });
    }, 50);
  }
};

// 更新图表
const updateChart = () => {
  if (!chartInstance || !props.options) return;

  const {
    title,
    xAxisData = [],
    series = [],
    iszoom = false,
    showMarkLine = false,
    customColors = [],
    isStacked = false,
    xAxisUnit = '',
    yAxisUnit = '',
    secondYAxisUnit = '',
    showSecondYAxis = false,
    // 新增配置，用于控制是否隐藏坐标轴和刻度
    hideXAxis = false,
    hideYAxis = false
  } = props.options;

  const option = {
    ...createBaseOption(),
    title: title ? {
      text: title,
      textStyle: {
        fontSize: 16,
        fontWeight: 500,
        color: "#333",
      },
      top: 10,
      left: "3%",
    } : null,
    grid: {
      top: title ? "15%" : "12%",
      right: showSecondYAxis ? "8%" : "5%",
      bottom: iszoom ? "20%" : "5%",
      left: "5%",
      containLabel: true,
    },
    legend: series.length > 1 ? {
      data: series.map((s) => s.name),
      top: '0%',
      left: 'center',
      icon: "circle",
      itemWidth: 8,
      itemHeight: 8,
      itemGap: 16,
      textStyle: { fontSize: 12, color: "#333" },
    } : null,
    xAxis: {
      data: xAxisData,
      name: xAxisUnit,
      nameLocation: 'end',
      nameTextStyle: {
        padding: [30, 0, 0, 0]
      },
      boundaryGap: true,
      // 隐藏坐标轴和刻度
      axisLine: {
        show: !hideXAxis,
        lineStyle: { color: "#aaa", width: 1, type: "solid" },
      },
      axisTick: { show: !hideXAxis },
      axisLabel: { fontSize: 12 },
      // 当 hideXAxis 为 true 时隐藏分割线
      splitLine: {
        show: !hideXAxis,
        lineStyle: { color: "#f0f0f0", type: "dashed" },
      },
    },
    yAxis: showSecondYAxis ? [
      {
        type: 'value',
        name: yAxisUnit,
        axisLabel: {
          fontSize: 12,
          formatter: '{value}' + (yAxisUnit ? ' ' + yAxisUnit : ''),
          // 当 hideYAxis 为 true 时隐藏刻度值
          show: !hideYAxis
        },
        // 隐藏坐标轴和刻度
        axisLine: {
          show: !hideYAxis,
          lineStyle: { color: "#aaa", width: 1, type: "solid" },
        },
        axisTick: { show: !hideYAxis },
        // 当 hideYAxis 为 true 时隐藏分割线
        splitLine: {
          show: !hideYAxis,
          lineStyle: { color: "#f0f0f0", type: "dashed" },
        },
      },
      {
        type: 'value',
        name: secondYAxisUnit,
        nameLocation: 'end',
        position: 'right',
        axisLabel: {
          fontSize: 12,
          formatter: '{value}' + (secondYAxisUnit ? ' ' + secondYAxisUnit : ''),
          // 当 hideYAxis 为 true 时隐藏刻度值
          show: !hideYAxis
        },
        // 隐藏坐标轴和刻度
        axisLine: {
          show: !hideYAxis,
          lineStyle: { color: "#aaa", width: 1, type: "solid" },
        },
        axisTick: { show: !hideYAxis },
        // 当 hideYAxis 为 true 时隐藏分割线
        splitLine: {
          show: false
        }
      }
    ] : {
      axisLabel: {
        fontSize: 12,
        formatter: '{value}' + (yAxisUnit ? ' ' + yAxisUnit : ''),
        // 当 hideYAxis 为 true 时隐藏刻度值
        show: !hideYAxis
      },
      // 隐藏坐标轴和刻度
      axisLine: {
        show: !hideYAxis,
        lineStyle: { color: "#aaa", width: 1, type: "solid" },
      },
      axisTick: { show: !hideYAxis },
      // 当 hideYAxis 为 true 时隐藏分割线
      splitLine: {
        show: !hideYAxis,
        lineStyle: { color: "#f0f0f0", type: "dashed" },
      },
    },
    series: createSeriesConfig(
      series,
      customColors.length > 0 ? customColors : colorPalette,
      isStacked,
      showMarkLine
    ),
  };

  if (iszoom) {
    let start = 0;
    let end = 100;
    if (xAxisData.length > 200) {
      end = 20; // 显示前20%
    }
    option.dataZoom = [
      {
        type: "slider",
        show: true,
        start: start,
        end: end,
        height: 20,
      },
    ];
  }

  chartInstance.setOption(option);
};

// 创建 resize 处理函数
const handleResize = debounce(() => {
  if (chartInstance && !isResizing) {
    isResizing = true;
    forceResize();
    isResizing = false;
  }
}, 200);

// 初始化图表
const initChart = () => {
  if (chartRef.value) {
    chartInstance = echarts.init(chartRef.value, props.theme, {
      renderer: "svg",
    });
    updateChart();

    if (props.responsive) {
      resizeObserver = new ResizeObserver(handleResize);
      resizeObserver.observe(chartRef.value);
      window.addEventListener("resize", handleResize);
    }
  }
};

// 监听配置变化
watch(
  () => props.options,
  (newOptions) => {
    if (newOptions) {
      updateChart();
    }
  },
  { deep: true }
);

// 生命周期钩子
onMounted(() => {
  initChart();
});

onUnmounted(() => {
  if (resizeObserver) {
    resizeObserver.disconnect();
    resizeObserver = null;
  }
  if (chartInstance) {
    chartInstance.dispose();
    chartInstance = null;
  }
  window.removeEventListener("resize", handleResize);
});

onActivated(() => {
  if (chartInstance) {
    forceResize();
  }
});
</script>

<style scoped>
.chart-container {
  position: relative;
  min-height: 200px;
}
</style>